template <typename T>

class mpmc_bounded_queue {
 public:
  mpmc_bounded_queue(size_t buffer_size)

      : buffer_(new cell_t[buffer_size])

        ,
        buffer_mask_(buffer_size - 1)

  {
    assert((buffer_size >= 2) &&

           ((buffer_size & (buffer_size - 1)) == 0));

    for (size_t i = 0; i != buffer_size; i += 1)

      buffer_[i].sequence_.store(i, std::memory_order_relaxed);

    enqueue_pos_.store(0, std::memory_order_relaxed);

    dequeue_pos_.store(0, std::memory_order_relaxed);
  }

  ~mpmc_bounded_queue()

  {
    delete[] buffer_;
  }

  bool enqueue(T const &data)

  {
    cell_t *cell;

    size_t pos = enqueue_pos_.load(std::memory_order_relaxed);

    for (;;)

    {
      cell = &buffer_[pos & buffer_mask_];

      size_t seq = cell->sequence_.load(std::memory_order_acquire);

      intptr_t dif = (intptr_t)seq - (intptr_t)pos;

      if (dif == 0)

      {
        if (enqueue_pos_.compare_exchange_weak

            (pos, pos + 1,
             std::
                 memory_order_relaxed))  // 尝试更新pos值，如果没有更新则继续for循环得到pos,并尝试下一次更新pos值

          break;
      }

      else if (dif < 0)

        return false;

      else

        pos = enqueue_pos_.load(std::memory_order_relaxed);
    }

    cell->data_ = data;

    cell->sequence_.store(
        pos + 1,
        std::memory_order_release);  // 被写入的位置标识已经写过  与
                                     // memory_order_acquire
                                     // 一起对sequence_的操作，保证是atomic的

    return true;
  }

  bool dequeue(T &data)

  {
    cell_t *cell;

    size_t pos = dequeue_pos_.load(std::memory_order_relaxed);

    for (;;)

    {
      cell = &buffer_[pos & buffer_mask_];

      size_t seq =

          cell->sequence_.load(std::memory_order_acquire);

      intptr_t dif = (intptr_t)seq - (intptr_t)(pos + 1);

      if (dif == 0)

      {
        if (dequeue_pos_.compare_exchange_weak

            (pos, pos + 1, std::memory_order_relaxed))

          break;
      }

      else if (dif < 0)

        return false;

      else

        pos = dequeue_pos_.load(std::memory_order_relaxed);
    }

    data = cell->data_;

    cell->sequence_.store

        (pos + buffer_mask_ + 1,
         std::memory_order_release);  // 被读取的位置做标识表示已经读过

    return true;
  }

 private:
  struct cell_t

  {
    std::atomic<size_t> sequence_;

    T data_;
  };

  static size_t const cacheline_size = 64;

  typedef char cacheline_pad_t[cacheline_size];

  cacheline_pad_t pad0_;

  cell_t *const buffer_;

  size_t const buffer_mask_;

  cacheline_pad_t pad1_;

  std::atomic<size_t> enqueue_pos_;

  cacheline_pad_t pad2_;

  std::atomic<size_t> dequeue_pos_;

  cacheline_pad_t pad3_;

  mpmc_bounded_queue(mpmc_bounded_queue const &);

  void operator=(mpmc_bounded_queue const &);
};
